<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>HoneHoneClock</title>
  <style>
    * {
      padding: 0;
      margin: 0;
    }
    html, body {
      width: 100%;
      height: 100%;
    }
    body {
      background-color: lightcyan;
    }
    canvas {
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      z-index: 1;
    }
  </style>
</head>
<body>
<canvas class="canvas"></canvas>
<script src="pixi_5.3.4.min.js"></script>
<script src="Stats.min.js"></script>
<script>

  (async function () {
    const stats = new Stats()
    document.body.appendChild(stats.domElement)

    let pageWidth = 0
    let pageHeight = 0

    let clockHour1, clockHour2
    let clockMin1, clockMin2
    let clockSec1, clockSec2
    const $canvas = document.querySelector('canvas')
    const renderer = new PIXI.Renderer({
      view: $canvas,
      width: pageWidth,
      height: pageHeight,
      transparent: true,
      autoDensity: true,
      antialias: true
    })

    // 人体时钟
    class Clock extends PIXI.Container {
      constructor (name) {
        super()
        const textures = loader.resources[honeHoneClockJson].textures
        let frames = []
        let aniData = []
        if (this.frames) {
          frames = this.frames
          aniData = this.aniData
        }
        else {
          aniData = [
            {
              prefix: '0',
              count: 6,
              frameFrom: -1,
              frameTo: -1,
            },
            {
              prefix: '1',
              count: 9,
              frameFrom: -1,
              frameTo: -1,
            },
            {
              prefix: '2',
              count: 7,
              frameFrom: -1,
              frameTo: -1,
            },
            {
              prefix: '3',
              count: 6,
              frameFrom: -1,
              frameTo: -1,
            },
            {
              prefix: '4',
              count: 9,
              frameFrom: -1,
              frameTo: -1,
            },
            {
              prefix: '5',
              count: 14,
              frameFrom: -1,
              frameTo: -1,
            },
            {
              prefix: '6',
              count: 7,
              frameFrom: -1,
              frameTo: -1,
            },
            {
              prefix: '7',
              count: 10,
              frameFrom: -1,
              frameTo: -1,
            },
            {
              prefix: '8',
              count: 7,
              frameFrom: -1,
              frameTo: -1,
            },
            {
              prefix: '9',
              count: 9,
              frameFrom: -1,
              frameTo: -1,
            },
          ]
          let k = 0
          for (let i = 0; i < aniData.length; i++) {
            const data = aniData[i]
            data.frameFrom = k
            for (let j = 1; j <= data.count; j++) {
              k++
              frames.push(textures[`${data.prefix}(${j}).png`])
            }
            data.frameTo = k - 1
          }
          this.frames = frames
          this.aniData = aniData
        }
        const ani = new PIXI.AnimatedSprite(frames)
        ani.anchor.set(0.5, 1)
        ani.animationSpeed = 0.4

        this.stopAt = -1
        ani.onFrameChange = () => {
          if (ani.currentFrame === this.stopAt) {
            ani.stop()
          }
        }
        this.addChild(ani)
        this.name = name
        this.ani = ani
        this.num = -1
      }

      set number (number) {
        if (this.num !== number) {
          this.num = number
          this.stopAt = this.aniData[number].frameTo
          this.ani.gotoAndPlay(this.aniData[number].frameFrom)
        }
      }
    }

    const stage = new PIXI.Container()
    stage.name = 'stage'
    let clockWrap

    const ticker = new PIXI.Ticker()
    let now = new Date()
    let lastTime = now.getTime()
    const loop = function () {
      stats.begin()
      now = new Date()
      if (now.getTime() - lastTime >= 1000) {
        let hours = now.getHours()
        if (hours > 9) {
          clockHour1.number = Math.floor(hours / 10)
          clockHour2.number = hours % 10
        }
        else {
          clockHour1.number = 0
          clockHour2.number = hours
        }

        let minutes = now.getMinutes()
        if (minutes > 9) {
          clockMin1.number = Math.floor(minutes / 10)
          clockMin2.number = minutes % 10
        }
        else {
          clockMin1.number = 0
          clockMin2.number = minutes
        }

        let seconds = now.getSeconds()
        if (seconds > 9) {
          clockSec1.number = Math.floor(seconds / 10)
          clockSec2.number = seconds % 10
        }
        else {
          clockSec1.number = 0
          clockSec2.number = seconds
        }
        lastTime = now.getTime()
      }
      renderer.render(stage)
      stats.end()
    }

    ticker.add(loop)

    const honeHoneClockJson = 'HoneHoneClock.json'
    const loader = new PIXI.Loader()
    loader.add([honeHoneClockJson])
    loader.onComplete.add(async (res) => {
      clockWrap = new PIXI.Container()
      clockWrap.pivot.set(600 * 0.5, -70)
      clockWrap.position.set(pageWidth * 0.5, pageHeight * 0.5)

      clockHour1 = new Clock('hour')
      clockHour2 = new Clock('hour')
      clockMin1 = new Clock('min')
      clockMin2 = new Clock('min')
      clockSec1 = new Clock('sec')
      clockSec2 = new Clock('sec')
      clockHour1.position.set(50, 0)
      clockHour2.position.set(150, 0)
      clockMin1.position.set(300, 0)
      clockMin2.position.set(400, 0)
      clockSec1.position.set(550, 0)
      clockSec2.position.set(650, 0)
      clockWrap.addChild(clockHour1)
      clockWrap.addChild(clockHour2)
      clockWrap.addChild(clockMin1)
      clockWrap.addChild(clockMin2)
      clockWrap.addChild(clockSec1)
      clockWrap.addChild(clockSec2)

      const indicator = new PIXI.Sprite(PIXI.Texture.WHITE)
      indicator.name = 'indicator'
      indicator.alpha = 0.5
      indicator.width = 700
      indicator.height = 180
      // indicator.anchor.set(0.5, 0.5)
      indicator.position.set(0, -170)
      indicator.visible = false
      clockWrap.addChild(indicator)

      let pickTime = 0 // 打点时间
      let pickX = 0 // 打点位置
      let objStartX = 0
      let objStartY = 0
      let startPageX = 0
      let startPageY = 0
      let deltaX = 0
      let deltaY = 0
      let isTap = false
      let dragging = false
      const onDragStart = function (pageX, pageY) {
        pickTime = performance.now()
        dragging = true
        isTap = true
        pickX = pageX
        startPageX = pageX
        startPageY = pageY
        objStartX = clockWrap.x
        objStartY = clockWrap.y
      }

      const onDragMove = function (pageX, pageY, e) {
        if (dragging) {
          deltaX = pageX - startPageX
          deltaY = pageY - startPageY
          if (isTap && (Math.abs(deltaX) > 2 || Math.abs(deltaY) > 2)) {
            isTap = false
          }
          if (!isTap) {
            clockWrap.position.set(objStartX + deltaX, objStartY + deltaY)
          }
        }
      }

      const onDragEnd = function (pageX, pageY, e) {
        if (dragging) {
          dragging = false
          isTap = false
        }
      }

      indicator.interactive = true
      indicator.buttonMode = true
      indicator.on('pointerdown', e => onDragStart(e.data.global.x, e.data.global.y, e))
      $canvas.ontouchmove = e => onDragMove(e.touches[0].pageX, e.touches[0].pageY)
      $canvas.ontouchend = e => onDragEnd(e.changedTouches[0].pageX, e.changedTouches[0].pageY, e)
      $canvas.onmousemove = e => onDragMove(e.pageX, e.pageY, e)
      $canvas.onmouseup = e => onDragEnd(e.pageX, e.pageY, e)

      clockWrap.interactive = true
      let lastClickAt = 0
      clockWrap.on('pointertap', function () {
        if (performance.now() - lastClickAt < 300) {
          indicator.visible = !indicator.visible
          lastClickAt = 0
        }
        else {
          lastClickAt = performance.now()
        }
      })

      stage.addChild(clockWrap)

      // 开始动画循环
      ticker.start()
    })
    loader.load()

    const onResize = (e) => {
      pageWidth = document.body.clientWidth
      pageHeight = document.body.clientHeight
      if (clockWrap) {
        clockWrap.position.set(pageWidth * 0.5, pageHeight * 0.5)
      }
      renderer.resize(pageWidth, pageHeight)
    }

    onResize()

    window.onresize = onResize
  })()
</script>
</body>
</html>
